﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;

using WAF.DAO;

namespace WAF.EntityFramework
{
    public class EntityAction
    {
        #region Insert

        /// <summary>
        /// 向数据库中增加一条实体类记录
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>自增长字段值</returns> 
        public static long Insert(Entity entity)
        {
            long autoIncrementID;
            EntitySession action = new EntitySession();

            action.OpenConnection();

            try
            {
                autoIncrementID = action.Insert(entity);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            finally
            {
                action.CloseConnection();
            }

            return autoIncrementID;
        }

        #endregion

        #region Update

        /// <summary>
        /// 更新数据库中的一条实体类记录
        /// </summary>
        /// <param name="entity">实体类</param>
        public static void Update(Entity entity)
        {
            EntitySession action = new EntitySession();

            action.OpenConnection();

            try
            {
                action.Update(entity);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            finally
            {
                action.CloseConnection();
            }
        }

        #endregion

        #region Delete

        /// <summary>
        /// 数据库中删除一条实体类记录
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="Id">>实体类的id值</param>
        public static void Delete(Type entityType, long Id)
        {
            Entity entity = (Entity)Activator.CreateInstance(entityType);
            entity.Id = Id;

            EntityAction.Delete(entity);
        }

        /// <summary>
        /// 从数据库中删除一条实体类记录
        /// </summary>
        /// <param name="entity">实体类</param>
        public static void Delete(Entity entity)
        {
            EntitySession action = new EntitySession();

            action.OpenConnection();

            try
            {
                action.Delete(entity);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            finally
            {
                action.CloseConnection();
            }
        }

        #endregion

        #region Save

        /// <summary>
        /// 保存实体数据（如果该实体已存在则执行增加操作，否则执行更新操作）
        /// </summary>
        /// <param name="entity">实体类</param>
        public static void Save(Entity entity)
        {
            EntitySession action = new EntitySession();

            action.BeginTransaction();

            try
            {
                action.Save(entity);
                action.CommitTtransaction();
            }
            catch (Exception ex)
            {
                action.RollbackTtransaction();
                throw ex.InnerException;
            }
        }

        #endregion

        #region Select

        /// <summary>
        /// 创建实体类并获取实体类各字段值
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="id">主键值</param>
        /// <param name="dbAccess">数据库访问组件</param>
        /// <returns>实体类</returns>
        public static T Select<T>(long id) where T : Entity
        {
            return (T)EntityAction.Select(typeof(T), id);
        }

        /// <summary>
        /// 创建实体类并获取实体类各字段值
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="id">主键值</param>
        /// <param name="dbAccess">数据库访问组件</param>
        /// <returns>实体类</returns>
        public static object Select(string entityName, long id)
        {
            return EntityAction.Select(Type.GetType(entityName), id);
        }

        /// <summary>
        /// 创建实体类并获取实体类各字段值
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="id">主键值</param>
        /// <param name="dbAccess">数据库访问组件</param>
        /// <returns>实体类</returns>
        public static object Select(Type entityType, long id)
        {
            EntitySession action = new EntitySession();

            action.OpenConnection();
            object entity = action.Select(entityType, id);
            action.CloseConnection();

            return entity;
        }

        /// <summary>
        /// 创建满足检索条件的实体类数组
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="selectSql">检索SQL语句</param>
        /// <param name="parms">SQL语句参数</parms>
        /// <returns>实体类数组</returns>
        public static T[] Select<T>(string selectSql = "", DbParameters parms = null) where T : Entity
        {
            return (T[])EntityAction.Select(typeof(T), selectSql, parms).ToArray(typeof(T));
        }

        /// <summary>
        /// 创建满足检索条件的实体类数组
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="selectSql">检索SQL语句</param>
        /// <param name="parms">SQL语句参数</param>
        /// <returns>实体类数组</returns>
        public static ArrayList Select(Type entityType, string selectSql = "", DbParameters parms = null)
        {
            EntitySession action = new EntitySession();

            action.OpenConnection();
            ArrayList entities = action.Select(entityType, selectSql, parms);
            action.CloseConnection();

            return entities;
        }

        #endregion

        #region Exist

        /// <summary>
        /// 查询数据库中相应实体类记录是否存在
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>存在返回true,不存在返回false</returns>
        public static bool Exist(Entity entity)
        {
            bool result;
            EntitySession action = new EntitySession();

            action.OpenConnection();

            try
            {
                result = action.Exist(entity);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            finally
            {
                action.CloseConnection();
            }

            return result;
        }

        #endregion

        #region Counts

        /// <summary>
        /// 指定数据库表中的记录总数
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>记录总数</returns>
        public static int Counts(Type entityType)
        {
            int count;
            EntitySession action = new EntitySession();

            action.OpenConnection();

            try
            {
                count = action.Counts(entityType);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            finally
            {
                action.CloseConnection();
            }

            return count;
        }

        #endregion

        #region GetGridData

        /// <summary>
        /// 创建满足搜索条件的实体类DataTable,只模糊查询要显示的字段和关联字段（限于支持limit的数据库）
        /// </summary>
        /// <param name="entityType">实体类名称</typeparam>
        /// <param name="searchTxt">搜索字符串</param>
        /// <param name="totel">记录总数（不受limit影响）</param>
        /// <param name="viewIdField">是否将ID字段显示为其对应的名称字段（默认为显示名称字段）</param>
        /// <param name="pageNo">当前页数</param>
        /// <param name="pageSzie">每页记录数</param>
        /// <returns>用于Grid显示的DataTable</returns>
        public static DataTable GetGridData(Type entityType, string searchTxt, out int totel, bool viewIdField = false, int pageNo = 0, int pageSzie = 0)
        {
            string tbName = entityType.Name;

            StringBuilder sbSelect = new StringBuilder("SELECT ");
            StringBuilder sbFrom = new StringBuilder(" FROM ").Append(tbName);
            StringBuilder sbWhere = new StringBuilder(" WHERE ");

            //遍历显示字段，生成SQL语句
            foreach (PropertyInfo pInfo in EntitySession.GetPropertiesOrder(entityType))
            {
                string fieldName = tbName + "." + pInfo.Name;
                EntityFieldAttribute fAttribute = EntitySession.GetFieldCustomAttributes(pInfo);

                //只显示标记为可显示的字段
                if (!fAttribute.IsDisplay) continue;

                if (fAttribute.RefTable == "")
                {
                    sbSelect.Append(fieldName).Append(" as ").Append(pInfo.Name).Append(",");
                    //不模糊查询ID字段
                    if(!fAttribute.IsPrimaryKey) sbWhere.Append(fieldName).Append(" like @search or ");
                }
                else
                {
                    if (viewIdField)
                        sbSelect.Append(fieldName).Append(" as ").Append(pInfo.Name).Append(",");
                    else
                        sbSelect.Append(fAttribute.RefTable).Append(".").Append(fAttribute.RefLableField).Append(" as ").Append(pInfo.Name).Append(",");

                    sbFrom.Append(" join ").Append(fAttribute.RefTable)
                          .Append(" on ").Append(fieldName).Append("=").Append(fAttribute.RefTable).Append(".").Append("id");

                    sbWhere.Append(fAttribute.RefTable).Append(".").Append(fAttribute.RefLableField).Append(" like @search or ");
                }
            }

            if (searchTxt != "")
                sbWhere.Replace("or ", "", sbWhere.Length - 3, 3);
            else
                sbWhere = sbWhere.Clear();

            sbSelect.Replace(",", "", sbSelect.Length - 1, 1);
            sbSelect.Append(sbFrom.ToString()).Append(sbWhere.ToString());

            //分页
            if (pageNo != 0 && pageSzie != 0)
            {
                int pageOffset = (pageNo - 1) * pageSzie;
                sbSelect.Append(" limit ").Append(pageOffset).Append(",").Append(pageSzie);
            }

            //查询参数
            DbParameters parms = new DbParameters();
            parms.Add("@search", "%" + searchTxt + "%", DbType.String);

            //sbSelect.Append(";SELECT FOUND_ROWS();");

            //执行SQL语句
            DataSet ds = DbAccess.ExeDataSet(sbSelect.ToString(), parms);

            object t = DbAccess.ExeScalar(new StringBuilder("SELECT count(*) FROM ").Append(tbName).Append(sbWhere.ToString()).ToString(), parms);

            if (t != null)
                totel = int.Parse(t.ToString());
            else
                totel = 0;

            return ds.Tables[0];
        }

        #endregion

    }
}
